﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using GameCore;
using System.IO;
namespace GameLogic
{
    /// <summary>
    /// AsssetBundleManager管理器
    /// @author:dingjie
    /// </summary>
    public class AssetBundleManager : SingletonBehaviour<AssetBundleManager>
    {
        AssetBundleManifest manifest;
        /// <summary>
        /// ABLoader列表
        /// </summary>
        Dictionary<string, AssetBundleLoader> bundleMap = new Dictionary<string, AssetBundleLoader>();
        /// <summary>
        /// AB路径列表
        /// </summary>
        List<AssetBundleLoader> bundleList = new List<AssetBundleLoader>();
        /// <summary>
        /// AssetBundleLoader缓存池
        /// </summary>
        ObjectPool<AssetBundleLoader> loaderPool;
        /// <summary>
        /// 持久化路径
        /// </summary>
        string persistentDataPath;
        /// <summary>
        /// 流媒体资源
        /// </summary>
        string streamPath;
        /// <summary>
        /// manifest文件
        /// </summary>
        string manifestName;
        /// <summary>
        /// The update count.
        /// </summary>
        int updateCount;
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="pathPrefix">路径前缀</param>
        public void Init(string persistentDataPath, string streamPath, string manifestName)
        {
            this.persistentDataPath = persistentDataPath;
            this.streamPath = streamPath;
            loaderPool = new ObjectPool<AssetBundleLoader>(null, CollectAssetBundleLoader);
            InitManifest(manifestName);
        }


        private void Update()
        {
            updateCount++;
            if(updateCount==50){
				UpdateAssetBundles();
                updateCount = 0;
            }
        }


        /// <summary>
        /// 初始化Manifest文件
        /// </summary>
        /// <param name="manifestName"></param>
        void InitManifest(string manifestName)
        {
            string path = persistentDataPath + manifestName;
            if (!File.Exists(path))
            {
                path = streamPath + manifestName;
            }
            AssetBundle bundle = AssetBundle.LoadFromFile(path);
            this.manifest = bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

        /// <summary>
        /// 刷新AB文件
        /// </summary>
        void UpdateAssetBundles()
        {
            AssetBundleLoader loader = null;
            for (int i = 0; i < bundleList.Count; i++)
            {
                loader = bundleList[i];
                if (!loader.IsLoadFinish || loader.IsGlobal)
                {
                    continue;
                }
                if (loader.References.Count == 0)
                {
                    loader.LeftLife--;
                    if (loader.LeftLife <= 0)
                        loader.UnLoad();
                }
            }
        }

        /// <summary>
        /// 同步加载AB文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public AssetBundleLoader LoadAssetBundle(string path)
        {
            path = path.ToLower();
            AssetBundleLoader loader = null;
            if (!bundleMap.TryGetValue(path, out loader))
            {
                string[] dependences = manifest.GetAllDependencies(path);
                loader = GetLoader(path, dependences);
                bundleMap.Add(path, loader);
                bundleList.Add(loader);
                loader.LoadAssetBundle();
                AssetBundleLoader tmpLoader = null;
                for (int i = 0; i < dependences.Length; i++)
                {
                    tmpLoader = LoadAssetBundle(dependences[i]);
                    tmpLoader.AddReference(path);
                }
            }
            loader.LeftLife = 10;
            return loader;
        }


        /// <summary>
        /// 异步加载AB文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="action"></param>
        public AssetBundleLoader LoadAssetBundleAsyn(string path)
        {
            return LoadAssetBundleAsyn(path, null);
        }

        /// <summary>
        /// 异步加载AB文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="action"></param>
        public AssetBundleLoader LoadAssetBundleAsyn(string path, UnityAction<AssetBundleLoader> action)
        {
            path = path.ToLower();
            AssetBundleLoader loader = null;
            if (!bundleMap.TryGetValue(path, out loader))
            {
                string[] dependences = manifest.GetAllDependencies(path);
                loader = GetLoader(path, dependences);
                if (action != null)
                {
                    loader.AddListener(action);
                }
                bundleMap.Add(path, loader);
                bundleList.Add(loader);
                StartCoroutine(LoadAsssetBundleAsyn(loader));
            }
            else
            {
                if (action != null)
                {
                    action(loader);
                }
            }
            loader.LeftLife = 10;
            return loader;
        }

        /// <summary>
        /// 开启协程加载AB文件
        /// </summary>
        /// <param name="loader"></param>
        /// <returns></returns>
        IEnumerator LoadAsssetBundleAsyn(AssetBundleLoader loader)
        {
            List<AssetBundleLoader> list = ListPool<AssetBundleLoader>.Get();
            string dependence = string.Empty;
            AssetBundleLoader dependenceLoader = null;
            for (int i = 0; i < loader.Dependences.Length; i++)
            {
                dependence = loader.Dependences[i];
                dependenceLoader = LoadAssetBundleAsyn(dependence, null);
                dependenceLoader.AddReference(loader.Path);
                list.Add(dependenceLoader);
            }
            //先加载依赖项
            while (list.Count > 0)
            {
                if (list[0].IsLoadFinish)
                {
                    list.RemoveAt(0);
                    continue;
                }
                yield return null;
            }
            ListPool<AssetBundleLoader>.Release(list);
            //如果等待过程中,没有被同步加载,加载自己
            if (!loader.IsLoadFinish)
            {
                yield return loader.LoadAssetBundleAsyn();
            }
        }

        /// <summary>
        /// 获取Loader
        /// </summary>
        /// <param name="path"></param>
        /// <param name="dependences"></param>
        /// <returns></returns>
        AssetBundleLoader GetLoader(string path, string[] dependences)
        {

            string fullPath = GetFullPath(path);
            AssetBundleLoader loader = loaderPool.Get();
            loader.Init(path, fullPath, dependences);
            return loader;
        }

        /// <summary>
        /// 卸载AB文件
        /// </summary>
        /// <param name="path"></param>
        public void UnLoadAssetBundle(string path)
        {
            GameCore.Logger.Log("~~~~~~~~~UnLoadAssetBundle:" + path);
            AssetBundleLoader loader = null;
            if (bundleMap.TryGetValue(path, out loader))
            {
                loaderPool.Release(loader); bundleMap[path].UnLoad();
            }
        }

		/// <summary>
		/// 回收AssetBundleLoader,移除它对其他AB包的引用
		/// </summary>
		/// <param name="loader"></param>
		internal void CollectAssetBundleLoader(AssetBundleLoader loader)
        {
            GameCore.Logger.LogFormat("~~~~~~~~CollectAssetBundleLoader:{0}", loader.Path);
            bundleMap.Remove(loader.Path);
            bundleList.Remove(loader);
            loader.UnLoad();
            for (int i = 0; i < loader.Dependences.Length; i++)
            {
                bundleMap[loader.Dependences[i]].RemoveReference(loader.Path);
            }
        }

        /// <summary>
        /// 获取完整加载路径
        /// 备注：先到持久化数据文件夹下找，如果没有找到，到流媒体资源中加载
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        string GetFullPath(string path)
        {
            string fullPath = persistentDataPath + path;
            if (!File.Exists(fullPath))
                fullPath = streamPath + path;
            return fullPath;
        }

    }
}

